﻿// Copyright (c) 2012 Mokah Nnamezie & Andrew Cooper
// Neo4Net graph database - http://neo4net.codeplex.com
//
// This file is part of Neo4Net - a .Net port of the Neo4j graph database
//
// Neo4Net is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace Neo4Net.GraphDb
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Neo4Net.Compat;

    /// <summary>Defines relationship directions used when getting relationships from a node
    /// or when creating traversers.</summary>
    /// <remarks>
    /// A relationship has a direction from a node's point of view. If a node is the
    /// start node of a relationship it will be an <see cref="Outgoing"/> relationship
    /// from that node's point of view. If a node is the end node of a relationship
    /// it will be an <see cref="Incoming"/> relationship from that node's point of view.
    /// The <see cref="Both"/> direction is used when direction is of no importance, such
    /// as "give me all" or "traverse all" relationships that are either
    /// <see cref="Outgoing"/> or <see cref="Incoming"/>.
    /// </remarks>
    public class Direction : Enumeration<Direction>
    {
        // In neo4j Direction is an enum.  
        // This port to C# is insipired by the answers to this StackOverflow question 
        // http://stackoverflow.com/questions/1376312/whats-the-equivalent-of-javas-enum-in-c

        /// <summary>Defines outgoing relationships.</summary>
        public static readonly Direction Outgoing = new Direction("Outgoing", () => Incoming);
        /// <summary>Defines incoming relationships.</summary>
        public static readonly Direction Incoming = new Direction("Incoming", () => Outgoing);
        /// <summary>Defines both incoming and outgoing relationships.</summary>
        public static readonly Direction Both = new Direction("Both", () => Both);

        private readonly Func<Direction> reverse;

        private Direction(string name, Func<Direction> reverse) 
            : base (name)
        {
            this.reverse = reverse;
        }

        /// <summary>
        /// Reverses the direction returning <see cref="Incoming"/> if <c>this</c> equals
        /// <see cref="Outgoing"/>, <see cref="Outgoing"/> if <c>this</c> equals <see cref="Incoming"/> or
        /// <see cref="Both"/> if <c>this</c> equals <see cref="Both"/>.
        /// </summary>
        /// @return The reversed direction.
        public Direction Reverse()
        {
            return reverse();
        }
    }
}

